上下文管理器
最终,上下文管理器可能几乎与子程序(subroutine)本身一样重要。
在各种语言中 with 语句的作用不同,而且做的都是简单的事,虽然可以避免不
断使用点号查找属性,但是不会做事前准备和事后清理。
if语句之外的else块
else太个性了, 其他语言不同用 不用这个
两个风格
EAFP 这种就得看好哪个else语句了
取得原谅比获得许可容易(easier to ask for forgiveness than permission)。这是一
种常见的 Python 编程风格,先假定存在有效的键或属性,如果假定不成立,那么捕
获异常。这种风格简单明快,特点是代码中有很多 try 和 except 语句。与其他很多
语言一样(如 C 语言),这种风格的对立面是 LBYL 风格。
接下来,词汇表定义了 LBYL。
LBYL 先用这个吧
三思而后行(look before you leap)。这种编程风格在调用函数或查找属性或键
之前显式测试前提条件。与 EAFP 风格相反,这种风格的特点是代码中有很多 if 语
句。在多线程环境中,LBYL 风格可能会在“检查”和“行事”的空当引入条件竞争。例
如,对 if key in mapping: return mapping[key] 这段代码来说,如果在测试
之后,但在查找之前,另一个线程从映射中删除了那个键,那么这段代码就会失败。
这个问题可以使用锁或者 EAFP 风格解决。
上下文管理器和with块
上下文管理器协议包含 enter 和 exit 两个方法。with 语句开始运行时,会在上下文管理器对象上调用 enter 方法。
with 语句运行结束后,会在上下文管理器对象上调用 exit 方法,以此扮演 finally 子句的角色。
class LookingGlass:
def __enter__(self):
import sys
self.original_write = sys.stdout.write
sys.stdout.write = self.reverse_write
return 'JABBERWOCKY'
def reverse_write(self, text):
self.original_write(text[::-1])
def __exit__(self, exc_type, exc_value, traceback):
import sys
sys.stdout.write = self.original_write
if exc_type is ZeroDivisionError:
print('Please DO NOT divide by zero!')
return True
❻ 如果一切正常,Python 调用 exit 方法时传入的参数是 None, None, None;如
果抛出了异常,这三个参数是异常数据,如下所述。
解释器调用 enter 方法时,除了隐式的 self 之外,不会传入任何参数。传给
exit 方法的三个参数列举如下。
exc_type
异常类(例如 ZeroDivisionError)。
exc_value
异常实例。有时会有参数传给异常构造方法,例如错误消息,这些参数可以使用exc_value.args 获取。
traceback
traceback 对象。
@contextmanager 装饰器 哥还是写全的吧
能减少创建上下文管理器的样板代码量,因为不用编写一个完整的类,定义 enter 和 exit 方法,
而只需实现有一个 yield 语句的生成器,生成想让 enter 方法返回的值。
总结
else 不要用python哪个没朋友的 神奇else (不过要看懂)
上下文 with
def __enter__(self): 一般返回 self自己
def __exit__(self, exc_type, exc_value, traceback):
exc_type
异常类(例如 ZeroDivisionError)。exc_value
异常实例。有时会有参数传给异常构造方法,例如错误消息,这些参数可以使用exc_value.args 获取。traceback
traceback 对象。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。